import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import bean.ArtificalInfo;
import redis.RedisCluster;
import util.AES;
import util.ConfigUtils;
import util.ConnectionManager;
import util.DbUtils;

public class ArtificalMain {

	private static final Logger logger = LogManager.getLogger(ArtificalMain.class);

	private static List<String> list = new ArrayList<String>();

	private static final int SEND_COUNT = Integer.parseInt(ConfigUtils.getInstance().getValue("maxCount"));

	private static final String FILE_PATH = ConfigUtils.getInstance().getValue("filePath");

	private static final String SKEY = ConfigUtils.getInstance().getValue("sKey");

	private static final String FILE_BAK_PATH = ConfigUtils.getInstance().getValue("bakFilePath");
	private static final String  SENDER = ConfigUtils.getInstance().getValue("sender");
	private static final String  SENDER2 = ConfigUtils.getInstance().getValue("sender2");
	private static final String   MSISDN = ConfigUtils.getInstance().getValue("msisdn");
	public static String REDISIP = ConfigUtils.getInstance().getValue("redisIp");

	public static void main(String[] args) {
		ArtificalMain artificalMain = new ArtificalMain();
		List<ArtificalInfo> list = null;
		while (true) {
			try {
				// 1 ��ȡ�������ֹ�����������Ϣ
				list = artificalMain.getBatchNumber();
				// 2 ��ȡ���е����˹����ŷ�����ϸ
				 Map<String, Integer> map = artificalMain.getMgrArtificatinInfo();
				// 3 �����ļ����
				logger.info("���δ������ֹ��ļ�������" + list.size());
				for (ArtificalInfo artificalInfo : list) {
					if(map.get(artificalInfo.getMgrId()) == null){
						map.put(artificalInfo.getMgrId(), 0);
					}
					logger.info("�����ֹ��������:" + map.toString());
					artificalMain.parseFile(artificalInfo, map);
				}
				Thread.sleep(500);
			} catch (Exception e) {
				logger.error("�����г����쳣�������´�ѭ��");
				e.printStackTrace();
			}
			logger.info("**************************************");
		}
	}

	/**
	 * ��ѯ�����ѳ����ֹ����Ͷ�����Ŀ����ϸ
	 * @return Map<String, Integer>
	 * @throws SQLException
	 */
	private Map<String, Integer> getMgrArtificatinInfo() throws SQLException {
		String sql = "select t.mgrid,count(*) cnt from sms_artifical_detail t " +
				"where t.createtime>trunc(sysdate) and t.sendstate=1 group by t.mgrid";
		Connection conn = null;
		ResultSet rs = null;
		PreparedStatement pres = null;
		Map<String, Integer> map = new HashMap<String, Integer>();
		try {
			conn = ConnectionManager.getInstance().getConnection();
			pres = conn.prepareStatement(sql);
			rs = pres.executeQuery();
			while (rs.next()) {
				map.put(rs.getString("MGRID"), rs.getInt("CNT"));
			}
			logger.info("�����ѳ����ֹ����Ͷ�����Ŀ����ϸ:" + map.toString());
		} catch (SQLException e) {
			logger.error("��ѯ���մ����ֹ�������Ŀ����Ϣ");
			e.printStackTrace();
			throw e;
		} finally {
			DbUtils.closeQuietly(rs, pres, conn);
		}
		return map;
	}

	/**
	 * ��ȡ���˹����Ͷ��ŵ����ݼ���
	 * @return List<ArtificalInfo>
	 * @throws SQLException
	 */
	private List<ArtificalInfo> getBatchNumber() throws SQLException {
		Connection conn = null;
		ResultSet rs = null;
		PreparedStatement pres = null;
		ArtificalInfo aInfo = null;
		List<String> dealList = new ArrayList<String>();
		List<ArtificalInfo> list = new ArrayList<ArtificalInfo>();
		String sql = "select a.batch_number," +
				"       a.city_id," +
				"       a.id," +
				"       a.JOIN_FREQUENCY_ROOM," +
				"       a.OVER_EXPIRE," +
				"       decode(a.send_time, null, sysdate, a.send_time) send_time," +
				"       c.content," +
				"       c.name," +
				"       c.city_ext_id," +
				"       a.county_id" +
				"  from sms_artificial_record a," +
				"       esms_mgr_template_info c" +
				" where a.id = c.id" +
				"   and a.state = -1" +
				"   and (a.send_time is null or a.send_time <= sysdate)";
		try {
			conn = ConnectionManager.getInstance().getConnection();
			pres = conn.prepareStatement(sql);
			rs = pres.executeQuery();
			while (rs.next()) {
				aInfo = new ArtificalInfo();
				aInfo.setBatchNumber(rs.getString("BATCH_NUMBER"));
				aInfo.setCityId(rs.getString("CITY_ID"));
				aInfo.setMgrId(rs.getString("ID"));
				aInfo.setSendTime(rs.getString("SEND_TIME"));
				aInfo.setContent(rs.getString("CONTENT"));
				aInfo.setMgrName(rs.getString("NAME"));
				aInfo.setCityExtId(rs.getString("CITY_EXT_ID"));
				aInfo.setCountyId(rs.getString("COUNTY_ID"));

				aInfo.setJoinFrequencyRoom(rs.getString("JOIN_FREQUENCY_ROOM"));
				aInfo.setOverExpire(rs.getString("OVER_EXPIRE"));

				if(!dealList.contains(rs.getString("BATCH_NUMBER"))) {
					list.add(aInfo);
					dealList.add(rs.getString("BATCH_NUMBER"));
				}
			logger.info("���˹����Ͷ��ŵ����ݼ���:" + aInfo.toString());
			}
		} catch (SQLException e) {
			logger.error("��ѯ���κų����쳣");
			e.printStackTrace();
			throw e;
		} finally {
			DbUtils.closeQuietly(rs, pres, conn);
		}
		return list;
	}

	/**
	 * �����ļ��������
	 * @param aInfo
	 * @param map
	 */
	private void parseFile(ArtificalInfo aInfo, Map<String, Integer> map){
		String fileName = aInfo.getBatchNumber() + ".csv" ;
		File file = new File(FILE_PATH + fileName);
		ArtificalInfo artificalInfo = null;
		List<ArtificalInfo> allList = new ArrayList<ArtificalInfo>();
		List<ArtificalInfo> sendList = new ArrayList<ArtificalInfo>();
		logger.debug("�ļ�·����" + (FILE_PATH + fileName));
		if(!file.exists()){
			logger.error("δ�ҵ��ļ�" + fileName);
			if(!list.contains(fileName)) {
				list.add(fileName);
				sendWarnSms("δ�ҵ��ļ�" + fileName + "����ϵͳ�˹����͵����Ƿ��쳣��");
			}
		} else {
			String reStr;
			BufferedReader reader;
			try {
				reader = new BufferedReader(new FileReader(file));
				while((reStr = reader.readLine()) != null){
					if(!reStr.substring(0,1).equals("1")){
						continue;
					}
					String encryt = AES.encrypt(reStr.trim(), SKEY);
					artificalInfo = new ArtificalInfo();
					artificalInfo.setBatchNumber(aInfo.getBatchNumber());
					artificalInfo.setCityId(aInfo.getCityId());
					artificalInfo.setMgrId(aInfo.getMgrId());
					artificalInfo.setMsisdn(encryt.trim());
					artificalInfo.setContent(aInfo.getContent());
					artificalInfo.setSendTime(aInfo.getSendTime());
					artificalInfo.setState("-1");//Ĭ�ϵ���ʧ��
					artificalInfo.setSendState("1");//Ĭ��δ����
					artificalInfo.setMgrName(aInfo.getMgrName());
					artificalInfo.setSeqId(getSeqId());
					artificalInfo.setCityExtId(aInfo.getCityExtId());
					artificalInfo.setCountyId(aInfo.getCountyId());
					artificalInfo.setJoinFrequencyRoom(aInfo.getJoinFrequencyRoom());
					artificalInfo.setOverExpire(aInfo.getOverExpire());
					if(reStr.trim().length() != 11) {
						artificalInfo.setRemark("���벻���Ϲ���");
					} else if(map.get(aInfo.getMgrId()) == SEND_COUNT) {
						artificalInfo.setState("-1");
						artificalInfo.setRemark("�ѳ���һ�췢��" + SEND_COUNT + "��������");
					} else {
						artificalInfo.setState("0");//����ɹ�
						map.put(aInfo.getMgrId(), map.get(aInfo.getMgrId()) + 1);
						sendList.add(artificalInfo);
					}
					allList.add(artificalInfo);
				}
				reader.close();
				logger.info("�����Ͷ�������" + sendList.size() + " �ܼƣ�" + allList.size());
			} catch (Exception e) {
				logger.error("�ļ����������쳣������");
				e.printStackTrace();
			}
			try {
				this.sendSms(sendList, allList);
				this.moveFile(FILE_PATH + fileName, FILE_BAK_PATH + fileName);
			} catch (SQLException e) {
				logger.error("��������쳣���ȴ���һ�δ�������");
				int reCount = 0;//�쳣��¼��
				for (String batchNumber : list) {
					if(batchNumber.equals(aInfo.getBatchNumber())){
						reCount++;
					}
				}
				if(reCount < 3) {
					list.add(aInfo.getBatchNumber());
				} else if(reCount == 3) {
					list.add(aInfo.getBatchNumber());
					sendWarnSms("�����ֹ������ļ�" + fileName + "����3�γ����쳣�����飡");
				}
				logger.error("�쳣��¼��" + list.toString());
				e.printStackTrace();
			}
		}
	}

	/**
	 * ��ȡÿһ���ֹ��������к�
	 * @return ���к�
	 */
	private String getSeqId() {
		String seqId = "";
		Connection conn = null;
		PreparedStatement pres = null;
		ResultSet rs = null;
		String sql = "select seq_bomc_cmpp.nextval from dual";
		try {
			conn = ConnectionManager.getInstance().getConnection();
			pres = conn.prepareStatement(sql);
			rs = pres.executeQuery();
			if(rs.next()) {
				seqId = rs.getString(1);
			}
		} catch (SQLException e) {
			logger.error("��ȡ�˹��������к�ʧ��");
			seqId = System.currentTimeMillis() + "";
			e.printStackTrace();
		} finally {
			DbUtils.closeQuietly(rs, pres, conn);
		}
		return seqId;
	}

	/**
	 * �����ݲ�����ŷ��ͱ��˹����ż�¼������������״̬
	 * @param
	 * @param allList
	 * @throws SQLException
	 */
	private void sendSms(List<ArtificalInfo> sendList, List<ArtificalInfo> allList) throws SQLException {
		Connection conn = null;
		PreparedStatement pres1 = null;
		PreparedStatement pres2 = null;
		PreparedStatement pres3 = null;
		RedisCluster redisCluster= null;
		String key=null;
		String sql1 = "insert into esms_check_send(id,receiver,sender,content,result,create_date,modify_date,city_id,mgr_id,mgr_name,is_local,is_mark,seq_id,city_ext_id,county_id)" +
				"values(seq_bomc_cmpp.nextval,?,?,?,?,sysdate,sysdate,?,?,?,?,?,?,?,?)";
		String sql2 = "insert into sms_artifical_detail(batchnumber,cityid,mgrid," +
				"sendtime,msisdn,state,remark,sendstate,createtime,seqid,countyId) values(?,?,?,to_date(?,'yyyy-MM-dd hh24:mi:ss'),?,?,?,?,sysdate,?,?)";
		String sql3 = "update sms_artificial_record t set t.state = 0 where t.batch_number = ?";
		try {
			conn = ConnectionManager.getInstance().getConnection();
			conn.setAutoCommit(false);
			pres1 = conn.prepareStatement(sql1);
			pres2 = conn.prepareStatement(sql2);
			pres3 = conn.prepareStatement(sql3);
			for (ArtificalInfo artificalInfo : sendList) {
				pres1.setString(1, artificalInfo.getMsisdn());
				if("11".equals(artificalInfo.getCityId())){
				    pres1.setString(2, SENDER);
				}else{
				    pres1.setString(2, SENDER2);
				}
				pres1.setString(3, artificalInfo.getContent());
				pres1.setInt(4, -1);//Ĭ��δ����
				pres1.setString(5, artificalInfo.getCityId());
				pres1.setString(6, artificalInfo.getMgrId());
				pres1.setString(7, artificalInfo.getMgrName());
				pres1.setString(8, "1");//Ĭ������û�
				pres1.setString(9, "1");//1�����ֹ�����
				pres1.setString(10, artificalInfo.getSeqId());
				pres1.setString(11, artificalInfo.getCityExtId());
				pres1.setString(12, artificalInfo.getCountyId());
				logger.debug("ArtificalInfo:" + artificalInfo.toString());
				pres1.addBatch();
				String joinFrequencyRoom=artificalInfo.getJoinFrequencyRoom();
				int overExpire=Integer.valueOf(artificalInfo.getOverExpire())*24*60*60;

				//�������˹����ͺ���ѡ�����Ƶ�ο�
				if("1".equals(joinFrequencyRoom)){
					key=artificalInfo.getMsisdn()+"#"+artificalInfo.getMgrId();
					redisCluster=new RedisCluster(REDISIP);
					redisCluster.hset(key, "sendType", "ArtificialSend");
					redisCluster.expire(key, overExpire);
					logger.info("�������redisƵ�ο�,key:"+key);
				}
			}
			for (ArtificalInfo artificalInfo2 : allList) {
				pres2.setString(1, artificalInfo2.getBatchNumber());
				pres2.setString(2, artificalInfo2.getCityId());
				pres2.setString(3, artificalInfo2.getMgrId());
				pres2.setString(4, artificalInfo2.getSendTime().substring(0,19));
				pres2.setString(5, artificalInfo2.getMsisdn());
				pres2.setString(6, artificalInfo2.getState());
				pres2.setString(7, artificalInfo2.getRemark());
				pres2.setString(8, artificalInfo2.getSendState());
				pres2.setString(9, artificalInfo2.getSeqId());
				pres2.setString(10, artificalInfo2.getCountyId());
				logger.debug("ArtificalInfo:" + artificalInfo2.toString());
				pres2.addBatch();

				pres3.setString(1, artificalInfo2.getBatchNumber());
				pres3.addBatch();
			}
			pres1.executeBatch();
			pres2.executeBatch();
			pres3.executeBatch();

			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback();
				logger.error("����������������쳣�ع�:"+e.toString());
			} catch (SQLException e1) {
				logger.error("������������ع��쳣"+e1.toString());
				e1.printStackTrace();
				throw e1;
			}
			e.printStackTrace();
		} finally {
			DbUtils.closeQuietly(pres1);
			DbUtils.closeQuietly(pres2);
			DbUtils.closeQuietly(pres3, conn);
			if(null!=redisCluster){
				try {
					redisCluster.close();
				} catch (IOException e) {
					logger.error("redisCluster close exception"+e);
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * �ƶ��������ļ�������Ŀ¼��
	 * @param souceFile ԭ�ļ�
	 * @param removeFile �����ļ�
	 */
	private void moveFile(String souceFile,String removeFile){
		File fi = new File(souceFile);
		boolean flag = fi.renameTo(new File(removeFile));
		if(flag){
			logger.info("�ļ����ݳɹ���");
		}else{
			logger.error("�ļ�����ʧ�ܡ�������" + " �ļ�·��" + removeFile);
		}
	}

	/**
	 * ���͸澯����
	 * @param content
	 */
	public static void sendWarnSms(String content) {
		Connection conn = null;
		PreparedStatement pres = null;
		String sql = "insert into boss_sm_send(id,receiver,sender,content,result,city_id,create_date,modify_date)" +
				"values(seq_bomc_cmpp.nextval,?,?,?,?,?,sysdate,sysdate)";
		try {
			conn = ConnectionManager.getInstance().getConnection();
			pres = conn.prepareStatement(sql);
			String msisdn = MSISDN ;
			String[] msisdns = msisdn.split("\\,");
			for (String str : msisdns) {
				pres.setString(1, str);
				pres.setString(2, SENDER);
				pres.setString(3, content);
				pres.setInt(4, -1);//Ĭ��δ����
				pres.setInt(5, 14);//Ĭ���Ͼ�
				pres.addBatch();
			}
			pres.executeBatch();
		} catch (Exception e) {
			logger.error("�����������ʱ�����쳣������");
			e.printStackTrace();
		} finally {
			DbUtils.closeQuietly(pres, conn);
		}
	}
}
